package com.webxiaohua.pattern.simplefactory;

import com.google.inject.internal.util.Maps;
import com.webxiaohua.pattern.simplefactory.product.ProductA;
import com.webxiaohua.pattern.simplefactory.product.ProductB;
import lombok.SneakyThrows;

import java.io.File;
import java.net.URL;
import java.util.Map;

/**
 * @Author: shenxinhua
 * @Date: 10/14/21 1:14 PM
 * @Description:
 */
public class ProductFactory {

    // 违反开闭原则的实例创建
    public static IProduct createProduct(String name) {
        if (name == "ProductA") {
            return new ProductA();
        }
        if (name == "ProductB") {
            return new ProductB();
        }
        return null;
    }

    // 符合开闭原则的实例创建，饿汉式
    private static final Map<String, Class<?>> map = Maps.newHashMap();

    @SneakyThrows
    private static void loadMap() {
        // 获取本类的路径
        URL resource = ProductFactory.class.getResource("");
        assert resource != null;
        String path = resource.getPath();
        String newPath = path + File.separator + "product";
        File file = new File(newPath);
        File[] files = file.listFiles();
        // 找到product 的路径
        String productPath = ProductFactory.class.getPackage().getName() + ".product.";
        assert files != null;
        for (File f : files) {
            // 文件夹跳过
            if (f.isDirectory()) {
                continue;
            }
            // 不是类文件跳过
            if (!f.getName().endsWith(".class")) {
                continue;
            }
            Class<?> forClass = Class.forName(productPath + f.getName().replace(".class", ""));
            // 拿到类上的注解
            TypeMask[] typeMasks = forClass.getAnnotationsByType(TypeMask.class);
            // 没标注解的不取
            if (typeMasks.length < 1) {
                continue;
            }
            // 没有实现Product 接口的不取
            if (IProduct.class.isAssignableFrom(forClass)) {
                map.put(typeMasks[0].value(), forClass);
            }
        }
    }

    static {
        loadMap();
    }

    @SneakyThrows
    public static IProduct createProduct2(String name) {
        Class<?> clazz = map.get(name);
        if (clazz == null) {
            return null;
        }
        if (IProduct.class.isAssignableFrom(clazz)) {
            return (IProduct) clazz.newInstance();
        }
        return null;
    }

    // 符合开闭原则的实例创建，懒汉式
    @SneakyThrows
    public static IProduct createProduct3(String name) {
        // 获取当前path
        URL url = ProductFactory.class.getResource("");
        String path = url.getPath();
        String classFilePath = path + "product" + File.separator + name + ".class";
        File classFile = new File(classFilePath);
        if (!classFile.exists()) {
            return null;
        }
        // 得到对应class
        String classPath = ProductFactory.class.getPackage().getName() + ".product." + name;
        Class<?> clazz = Class.forName(classPath);
        // 获取class实例
        if (IProduct.class.isAssignableFrom(clazz)) {
            return (IProduct) clazz.newInstance();
        }
        return null;
    }
}
